package com.sky.service.rider.impl;

import com.sky.constant.MessageConstant;
import com.sky.dto.PickUpDTO;
import com.sky.exception.DataException;
import com.sky.mapper.common.*;
import com.sky.pojo.*;
import com.sky.result.Result;
import com.sky.service.rider.CourierTradeOrderService;
import com.sky.utils.MapUtils;
import com.sky.vo.CourierTradeOrderVO;
import com.sky.vo.OrderDetailVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
public class CourierTradeOrderServiceImpl implements CourierTradeOrderService {

    @Autowired
    private TradeOrderMapper tradeOrderMapper;

    @Autowired
    private CourierMapper courierMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ShortUrlInfoMapper shortUrlInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 根据运单的状态和骑手的id查询骑手的运单数据
     *
     * @param status
     * @param courierId
     * @return
     */
    @Override
    public Result<List<CourierTradeOrderVO>> queryPendingOrders(Integer status, Long courierId) {
        //1. 校验参数
        if(null == status || null == courierId){
            throw new DataException(MessageConstant.DATA_ERROR);
        }

        //2. 通过状态和骑手的id查询运单表的记录
        List<CourierTradeOrder> list = tradeOrderMapper.selectList(status, courierId);

        if(null != list && list.size() > 0){
            //3. 遍历每一个运算数据 并计算骑手与商家的距离 骑手与客户之间的记录 以及预计达到的时间 然后拷贝到vo中
            List<CourierTradeOrderVO> voList = new ArrayList<>(list.size());

            //查询骑手的信息-当前位置的坐标
            Courier courier = courierMapper.findById(courierId);

            for (CourierTradeOrder tradeOrder : list) {
                CourierTradeOrderVO vo = new CourierTradeOrderVO();
                BeanUtils.copyProperties(tradeOrder, vo);

                //计算骑手与商家的距离
                String addressedToLnglat = MapUtils.addressToLnglat(tradeOrder.getShopAddress());
                double distance = MapUtils.calculateDistance(addressedToLnglat, courier.getCurLocation());

                //骑手与客户之间的记录
                String customerToLnglat = MapUtils.addressToLnglat(tradeOrder.getCustomerAddress());
                double customerDistance = MapUtils.calculateDistance(customerToLnglat, addressedToLnglat);

                //预计达到的时间
                long time = Duration.between(LocalDateTime.now(), tradeOrder.getCustomerExpectedDeliveryTime()).get(ChronoUnit.SECONDS);

                vo.setShopAndCourierDistance(distance /1000);
                vo.setShopAndCustomerDistance(customerDistance /1000);
                vo.setCurrentTimeAndCustomerExpectedTime(time);

                voList.add(vo);
            }

            //4. 对vo数据进行排序 然后生成的他的展示的顺序id
            AtomicInteger sort = new AtomicInteger(1);
            voList = voList.stream()
                    .sorted(Comparator.comparing(CourierTradeOrderVO::getShopAndCustomerDistance))
                    .map(vo -> {
                        vo.setMarkSort(sort.getAndIncrement());
                        return vo;
                    })
                    .collect(Collectors.toList());

            return Result.success(voList);
        }

        //5. 封装并返回数据
        return Result.success();
    }

    @Override
    public Result queryTradeOrderByTradeNo(String tradeNo) {
        CourierTradeOrder courierTradeOrder = tradeOrderMapper.selectByOrderNumber(tradeNo);
        return Result.success(courierTradeOrder);
    }

    /**
     * 根据运单号查询运单里面的详情数据
     *
     * @param tradeNo
     * @return
     */
    @Override
    public Result<List<OrderDetailVO>> confirmPickUpList(String tradeNo) {
        //1. 校验参数
        if(StringUtils.isEmpty(tradeNo)){
            throw  new DataException(MessageConstant.DATA_ERROR);
        }

        //2. 通过运单号查询运单 然后判断运单是否存在
        CourierTradeOrder tradeOrder = tradeOrderMapper.selectByTradeNo(tradeNo);
        if(null == tradeOrder){
            throw  new DataException(MessageConstant.DATA_ERROR);
        }
        //3. 通过运单数据得到订单号 然后查询订单的详情数据
        List<OrderDetail> list = orderDetailMapper.findDetailsByNumber(tradeOrder.getOrderNumber());
        if(null != list && list.size()>0){
            //4. 封装结果并返回
            List<OrderDetailVO> voList = new ArrayList<>(list.size());

            for (OrderDetail orderDetail : list) {
                OrderDetailVO vo = new OrderDetailVO();
                BeanUtils.copyProperties(orderDetail, vo);

                voList.add(vo);
            }

            return Result.success(voList);
        }

        return Result.success();
    }

    /**
     * 确认取货或者确认送达
     *
     * @param pickUpDTO
     * @return
     */
    @Override
    @Transactional(readOnly = false)
    public Result<String> confirmPickUp(PickUpDTO pickUpDTO) {
        //1. 校验参数
        if(null == pickUpDTO || null == pickUpDTO.getTradeNo()){
            throw new DataException(MessageConstant.DATA_ERROR);
        }

        //2. 根据运单的id查询运单数据 然后判断运单是否存在
        CourierTradeOrder tradeOrder = tradeOrderMapper.selectByTradeNo(pickUpDTO.getTradeNo().toString());
        if(null == tradeOrder){
            throw new DataException(MessageConstant.DATA_ERROR);
        }

        Orders  orders = new Orders();
        orders.setNumber(tradeOrder.getOrderNumber());
        if(3 == pickUpDTO.getStatus()){
            //3. 更新运单的状态
            tradeOrder.setWaybillStatus(pickUpDTO.getStatus());
            tradeOrderMapper.updateStatusById(tradeOrder);

            //4. 更新订单的状态
            orders.setStatus(Orders.TOBEDELIVERED);
            orderMapper.updateStatusByNumber(orders);
        }else if(4 == pickUpDTO.getStatus()){
            //更新运单的状态和完成时间
            tradeOrder.setWaybillStatus(CourierTradeOrder.TRADE_COMPLETE);
            tradeOrder.setTradeCompleteTime(LocalDateTime.now());
            tradeOrderMapper.updateStatusAndCompleteTimeById(tradeOrder);

            //更新订单的状态和完成时间
            orders.setStatus(Orders.COMPLETE_ORDER);
            orders.setDeliveryTime(LocalDateTime.now());
            orderMapper.updateStatusAndDeliveryTimeByNumber(orders);

            //查询短链的数据 然后删除短链数据
            String code =  shortUrlInfoMapper.selectByTradeNo(pickUpDTO.getTradeNo());
            shortUrlInfoMapper.deleteByTradeNo(pickUpDTO.getTradeNo());

            //计算短链在bitmap中的索引位置
            int hashcode = code.hashCode();
            Long index = 0L;

            if(hashcode < 0){
                index = Math.abs(hashcode) + 2147483648l;
            }else {
                index = (long) hashcode;
            }
            //修改对应的索引位false 下次随机到这个code的时候就可以继续使用了
            redisTemplate.opsForValue().setBit("short_url", index, false);
        }


        return Result.success();
    }

}
